/**
* Class Name:iFulfillTrackTaskHistory
* Author: Accenture
* Date: 13-Jun-2011
* Requirement/Project Name: iFulfill
* Requirement/Project Description: Handles task history on fulfillment item for various scenarios like skip, new, updates
* Bhumika Udani    dt 20 October 2011     v2.0     Corrected the logic for type assignment while skipping a rejected/reworked item
* Sapna Jaamdar    dt 08 November 2011    v2.1     Bulkified the activity checklist code
* Bhumika Udani    dt 10 November 2011    v2.1     Changed the field assignment for rework related fields for method called on insertion
* Bhumika Udani    dt 14 November 2011    v2.2     replaced ifulfill record type for notes with ifulfill_Manual_Notes 
* Bhumika Udani    dt 17 November 2011    v2.3     Enchancement request 382, included type 'Skip' for Task history records
* Bhumika Udani    dt 30 January  2012    v2.4     Defect fix for defect 559
* Michael Shu fix the issue of AD-30173 Change Flow not complete in EFS
**/

Public with sharing class iFulfillTrackTaskHistory{
     
               
     /**Method called from isInsert. Creates task history records**/
     
     public static void createNewStepHistory(list<Fullfilment_Item__c> FI){
           list<Fulfillment_Step_History__c> FSHlist = new List<Fulfillment_Step_History__c>();
           Map<ID,String> createdByUserNameMap = new Map<ID,String>();            
           
           /* Add all Fulfillment id,created user into Map. Need to write explicit query to access createdby name*/
           
           for(Fullfilment_Item__c fItem:[Select id,CreatedBy.name from Fullfilment_Item__c where id in :FI]){           
               createdByUserNameMap.put(fItem.id,fItem.CreatedBy.name);                             
            }                               
           
           for(Fullfilment_Item__c fItem :FI){
                 Fulfillment_Step_History__c FSH = new Fulfillment_Step_History__c();                 
                 FSH.Stage__c                   = fItem.Current_Function_Name__c;   
                 FSH.Step__c                    = fItem.Current_Task_Name__c;
                 FSH.Target_Days_Function__c    = fItem.Current_Stage_Target_days__c;               
                 FSH.Target_Days_Task__c        = fItem.Current_Step_Target_days__c;                  
                 FSH.Fullfilment_Item__c        = fItem.id;
                 FSH.ownerId                    = fItem.createdById;
                 FSH.Status__c                  = fItem.Status__c; 
                 FSH.Task_Start_Date__c         = System.now();
                 FSH.Workflow_Id__c             = fItem.Workflow_Name__c;
                 FSH.Sequence__c                = fItem.Function_Sequence__c;
                 
                 /*To assign createdBy user of Fulfillment Item to Owner__c field */
                 if(createdByUserNameMap.containsKey(fItem.ID)){
                     FSH.Owner__c     = createdByUserNameMap.get(fItem.ID);
                     System.debug('fItem.Owner_Reporting__c'+fItem.Owner_Reporting__c+'FSH.Owner__c'+FSH.Owner__c);
                 }   
                 FSH.Task_Sequence__c           = fItem.Task_Sequence__c;
                 FSH.Dashboard_Function__c      = fItem.Task_Dashboard_Function__c;
                 FSH.Rework_Function__c         = fItem.Current_Function_Name__c;      
                 FSH.Rework_Task__c             = fItem.Current_Task_Name__c ;
                 FSH.Rework_Function_Sequence__c= fItem.Function_Sequence__c; 
                 FSH.Rework_Task_Sequence__c    = fItem.Task_Sequence__c;
                 FSH.type__c                    = IfullfillTextConstant.FI_NEW;                                                                            
                
                 FSHlist.add(FSH);                 
           }
           if(FSHlist.size()>0){
           		try{
                     Insert FSHlist;
                }catch(dmlException insertException){
                     GeneralConstants.mailAnyExceptionToMe('createNewStepHistory Exception','createNewStepHistory',insertException);
             	}
           }
     }
     
     /** Create Step history record for the current functions's skipped tasks. **/
     /** Called from MoveNextController  **/
      
     public static void createNewStepHistoryForRemainingCurrentTaskSkip(Fullfilment_Item__c FI,Workflow_Stage__c workflowStage,List<Wokflow_Steps__c> stepList,String oldFIOwnerName,ID oldFIOwnerId){         
        
         system.debug('Entered this method ---> createNewStepHistoryForRemainingCurrentTaskSkip');         
         string fetchTaskString;
         string newTaskString;
         set<string> fetchedTaskSet= new set<string>();

         list<Fulfillment_Step_History__c> FSHSkipList = new List<Fulfillment_Step_History__c>();             
         Fulfillment_Step_History__c oldestRecord = [select id,Type__c,Fullfilment_Item__c , Task_Start_Date__c, Task_End_Date__c from Fulfillment_Step_History__c where Fullfilment_Item__c = :FI.id  and Task_End_Date__c =null order by Task_Start_Date__c DESC limit 1];         
         //Fulfillment_Step_History__c fetchTaskHistoryList = [select Type__c,Fullfilment_Item__c , Stage__c, Step__c from Fulfillment_Step_History__c where Fullfilment_Item__c = :FI.id ];         
         
         for(Fulfillment_Step_History__c eTaskHistory :[select Type__c,Fullfilment_Item__c , Stage__c, Step__c from Fulfillment_Step_History__c where Fullfilment_Item__c = :FI.id ]){
             fetchTaskString = string.valueof(eTaskHistory.Fullfilment_Item__c)+string.valueof(eTaskHistory.Stage__c)+string.valueof(eTaskHistory.Step__c);
             fetchedTaskSet.add(fetchTaskString);
             }
         system.debug('Fetched Task list'+fetchedTaskSet);
         
         for(Wokflow_Steps__c skipStepList:stepList){
               Fulfillment_Step_History__c FSH = new Fulfillment_Step_History__c();                 
               FSH.Stage__c                   = workflowStage.name;   
               FSH.Step__c                    = skipStepList.name;
               FSH.Target_Days_Function__c    = workflowStage.Task_Target_Days__c;               
               FSH.Target_Days_Task__c        = skipStepList.Target_Days__c;                  
               FSH.Fullfilment_Item__c        = FI.id;
               FSH.Status__c                  = FI.Status__c; 
               FSH.Task_Start_Date__c         = System.now();
               FSH.Task_End_Date__c           = System.now(); 
               FSH.Workflow_Id__c             = FI.Workflow_Code__r.Workflow_Name__c;
               FSH.Sequence__c                = workflowStage.Sequence__c;
               FSH.Task_Sequence__c           = skipStepList.Sequence__c; 
               FSH.Owner__c                   = oldFIOwnerName; 
               FSH.ownerId                    = oldFIOwnerId;             
               FSH.Dashboard_Function__c      = FI.Previous_Dashboard__c;
               FSH.Rework_Function__c         = FI.Previous_Function__c;      
               FSH.Rework_Task__c             = FI.Previous_Task__c;
               FSH.Rework_Function_Sequence__c= FI.Previous_Function_Sequence__c;
               FSH.Rework_Task_Sequence__c    = FI.Previous_Task_Sequence__c;                              
               
               newTaskString = string.valueof(FSH.Fullfilment_Item__c)+string.valueof(FSH.Stage__c)+string.valueof(FSH.Step__c);
               system.debug('newTaskString'+newTaskString);
               
               /**below condition check to populate the rework fields with current values when in happy path**/
               if(!fetchedTaskSet.contains(newTaskString)){
   
                 FSH.Rework_Function__c         = workflowStage.name;
                 FSH.Rework_Function_Sequence__c= workflowStage.Sequence__c;      
                   
                 FSH.Rework_Task__c             = skipStepList.name;
                 FSH.Rework_Task_Sequence__c    = skipStepList.Sequence__c;
                 FSH.Dashboard_Function__c      = skipStepList.Dashboard_Function__c;
                 system.debug('FFSSHH '+FSH) ;  
               }

               
               /**Populate the 'Type' as per Rework/Reject on fulfillment Item **/
               
               /** if not null populate the value**/
               if(FI.In_Rework_Reject__c!=null){         
                        FSH.type__c = FI.In_Rework_Reject__c;      
                } 
               /** Use the value of previously created history record in case of skip and item is still not reached the original rework /reject task **/
               else if(FI.Previous_Function_Sequence__c > workflowStage.Sequence__c ){
                       if(oldestRecord.Type__c == IfullfillTextConstant.FI_REWORK ||oldestRecord.Type__c == IfullfillTextConstant.FI_REJECT){
                           FSH.type__c = oldestRecord.Type__c;
                   }
               }
               else if(FI.Previous_Function_Sequence__c == workflowStage.Sequence__c && FI.Previous_Task_Sequence__c > skipStepList.Sequence__c){
                       if(oldestRecord.Type__c == IfullfillTextConstant.FI_REWORK  ||oldestRecord.Type__c == IfullfillTextConstant.FI_REJECT){
                           FSH.type__c = oldestRecord.Type__c;
                   }
               }                                      
               
               /** In case of 'Skip' put the type as skip  
               else if(fetchedTaskSet.contains(newTaskString)){
                       FSH.type__c = IfullfillTextConstant.FI_SKIP;
                    }**/

               /** or else put the default value as new **/
               //else if(FI.In_Rework_Reject__c==null)
                 if(!fetchedTaskSet.contains(newTaskString))
                       {FSH.type__c = IfullfillTextConstant.FI_SKIP;}
               
               FSHSkipList.add(FSH);                                 
         }   
         try{     
               if(FSHSkipList.size()>0){
                         System.debug('Total List'+FSHSkipList);
                   Insert FSHSkipList;
                }
           }catch(Exception e){
                GeneralConstants.mailAnyExceptionToMe('iFulfillTrackTaskHistory','createNewStepHistoryForRemainingCurrentTaskSkip',e);
           }
    }     
     
       /**Create Step history record for the Skipped Functions.**/
       public static void createNewStepHistoryForSkip(Fullfilment_Item__c FI,List<Workflow_Stage__c> stageList,Map <ID,List<Wokflow_Steps__c>> stepMap,String oldFIOwnerName,ID oldFIOwnerId){           
           
           system.debug('Entered this method ---> createNewStepHistoryForSkip');
           string fetchTaskString;
           string newTaskString;
           set<string> fetchedTaskSet= new set<string>();

           list<Fulfillment_Step_History__c> FSHSkipList = new List<Fulfillment_Step_History__c>();                    
           Fulfillment_Step_History__c oldestRecord = [select id,Type__c,Fullfilment_Item__c , Task_Start_Date__c, Task_End_Date__c from Fulfillment_Step_History__c where Fullfilment_Item__c = :FI.id  and Task_End_Date__c =null order by Task_Start_Date__c DESC limit 1];
           
           for(Fulfillment_Step_History__c eTaskHistory :[select Type__c,Fullfilment_Item__c , Stage__c, Step__c from Fulfillment_Step_History__c where Fullfilment_Item__c = :FI.id ]){
             fetchTaskString = string.valueof(eTaskHistory.Fullfilment_Item__c)+string.valueof(eTaskHistory.Stage__c)+string.valueof(eTaskHistory.Step__c);
             fetchedTaskSet.add(fetchTaskString);
            }
            system.debug('Fetched Task list'+fetchedTaskSet);
           
           for(Workflow_Stage__c skipStageList:stageList){            
             if(stepMap.containsKey(skipStageList.id)){                             
                 
                 for(Wokflow_Steps__c skipStepList:stepMap.get(skipStageList.id)){       
                 
                     System.debug('Task details '+FI.Owner_Reporting__c +'workflow ..>'+FI.Workflow_Code__r.Workflow_Name__c);        
                     Fulfillment_Step_History__c FSH = new Fulfillment_Step_History__c();                 
                     FSH.Stage__c                   = skipStageList.name;   
                     FSH.Step__c                    = skipStepList.name;
                     FSH.Target_Days_Function__c    = skipStageList.Task_Target_Days__c;               
                     FSH.Target_Days_Task__c        = skipStepList.Target_Days__c;                  
                     FSH.Fullfilment_Item__c        = FI.id;
                     FSH.Status__c                  = FI.Status__c; 
                     FSH.Task_Start_Date__c         = System.now();
                     FSH.Task_End_Date__c           = System.now(); 
                     FSH.Workflow_Id__c             = FI.Workflow_Code__r.Workflow_Name__c;
                     FSH.Sequence__c                = skipStageList.Sequence__c;
                     FSH.Owner__c                   = oldFIOwnerName; 
                     FSH.ownerId                    = oldFIOwnerId;                      
                     FSH.Task_Sequence__c           = skipStepList.Sequence__c;
                     FSH.Dashboard_Function__c      = FI.Previous_Dashboard__c;
                     FSH.Rework_Function__c         = FI.Previous_Function__c;      
                     FSH.Rework_Task__c             = FI.Previous_Task__c;
                     FSH.Rework_Function_Sequence__c= FI.Previous_Function_Sequence__c;
                     FSH.Rework_Task_Sequence__c    = FI.Previous_Task_Sequence__c;                                    
                    
                     newTaskString = string.valueof(FSH.Fullfilment_Item__c)+string.valueof(FSH.Stage__c)+string.valueof(FSH.Step__c);
                     system.debug('newTaskString'+newTaskString);
                     
                     /**below condition check to populate the rework fields with current values when in happy path**/
                     if(!fetchedTaskSet.contains(newTaskString)){
   
                     FSH.Rework_Function__c         = skipStageList.name;
                     FSH.Rework_Function_Sequence__c= skipStageList.Sequence__c;      
                     
                     FSH.Rework_Task__c             = skipStepList.name;
                     FSH.Rework_Task_Sequence__c    = skipStepList.Sequence__c;
                     FSH.Dashboard_Function__c      = skipStepList.Dashboard_Function__c;
                     system.debug('FFSSHH '+FSH) ;  
                     }
                     system.debug('FPS ' + FI.Previous_Function_Sequence__c + 'stage sequ' + skipStageList.Sequence__c + 'FTS' + skipStepList.Sequence__c);

                     
                     /** Populate the 'Type' in case of skipped records by checking the previously created history record**/
                      if(FI.Previous_Function_Sequence__c > skipStageList.Sequence__c || (FI.Previous_Function_Sequence__c == skipStageList.Sequence__c && FI.Previous_Task_Sequence__c > skipStepList.Sequence__c)){
                               if(oldestRecord.Type__c == IfullfillTextConstant.FI_REWORK||oldestRecord.Type__c == IfullfillTextConstant.FI_REJECT){
                                           FSH.type__c = oldestRecord.Type__c;
                                   }
                         }
                      else if(FI.Previous_Function_Sequence__c == skipStageList.Sequence__c && FI.Previous_Task_Sequence__c > skipStepList.Sequence__c){
                               if(oldestRecord.Type__c == IfullfillTextConstant.FI_REWORK ||oldestRecord.Type__c == IfullfillTextConstant.FI_REJECT){
                                   FSH.type__c = oldestRecord.Type__c;
                               }
                      }    
                      /**Populate the 'Type' as per Rework/Reject on fulfillment Item    **/
                      else if(FI.In_Rework_Reject__c!=null){         
                        FSH.type__c = FI.In_Rework_Reject__c;      
                         }
                     
                      /** In case of 'Skip' put the type as skip 
                      else if(fetchedTaskSet.contains(newTaskString)){
                         FSH.type__c = IfullfillTextConstant.FI_SKIP;
                         }**/
   
                      /**else put the default value **/
                       //else if(FI.In_Rework_Reject__c==null){
                       if(!fetchedTaskSet.contains(newTaskString)){
                                FSH.type__c = IfullfillTextConstant.FI_SKIP;
                       }    
                                         
                     FSHSkipList.add(FSH);                                 
                 }
              }      
         }         
         try{     
               if(FSHSkipList.size()>0){
                         System.debug('Total List'+FSHSkipList);
                   Insert FSHSkipList;
                }
           }catch(dmlException e){
                GeneralConstants.mailAnyExceptionToMe('iFulfillTrackTaskHistory','createNewStepHistoryForSkip',e);
           }  
    }
    
    // create Notes record when Fulfillment Item is marked for Escalation
     public static void createNoteOnEscalation(list<Fullfilment_Item__c> FI ){                
                ID ifulfillNoteRecordTypeID = RecordTypeHelper.GetRecordTypeIdByDevName('Notes__c',  'ifulfill_Manual_Notes');
                list<Notes__c> fNotesList = new list<Notes__c>();         
                    for(Fullfilment_Item__c fItem :FI){                                        
                        Notes__c fI_note = new Notes__c();                        
                        fI_note.type__c = 'Escalation';
                      //  fI_note.Title__c ='Fulfillment Item Escalated Task Note';
                        fI_note.Notes__c=fItem.Escalation_Reason__c+' - '+fItem.Escalation_Notes__c;
                        fI_note.Fullfilment_Notes__c = fItem .id;                
                        fI_note.recordtypeid = ifulfillNoteRecordTypeID ;                
                        fNotesList.add(fI_note); 
                    } 
                    
                    try{
                    if(fNotesList.size()>0){ 
                        insert fNotesList;
                        }
                    }
                    catch(dmlexception NotesException){
                         GeneralConstants.mailAnyExceptionToMe('createNoteOnEscalation Exception occured','createNoteOnEscalation',NotesException);   
                     }  
        }
                         
     
           
     /** Method called from isUpdate. **/
     /** Creates history when either status or owner or task of FI changes **/
     public static void trackStatus(list<Fullfilment_Item__c> FI, boolean MovesForwardFunction, boolean MovesForwardTask, map<id, fullfilment_item__c> oldFIMap){
        system.debug(MovesForwardFunction + '' +MovesForwardTask);
        Datetime myDate = system.now();
        String sDate = String.valueOf(myDate);
        String tType = 'New';   
        
        list<Fulfillment_Step_History__c> FSHlist = new List<Fulfillment_Step_History__c>();         
        list<Notes__c> fNotesList = new list<Notes__c>();  
        set<id> fISet = new set<id>();    
        List<Fulfillment_Step_History__c> oldestRecordList = new List<Fulfillment_Step_History__c>();            
        List<Fulfillment_Step_History__c> updatedRecordList = new List<Fulfillment_Step_History__c>();                                
        
        /** Fetch all the 'Oldest'history record for the FI in the trigger.new**/
        oldestRecordList = [select id,Fullfilment_Item__c , Task_Start_Date__c, Task_End_Date__c from Fulfillment_Step_History__c where Fullfilment_Item__c in : FI and Task_End_Date__c =null order by Task_Start_Date__c DESC ];                
        
        if(oldestRecordList.size()>0){        
        /** Update the end task date for the 'nth' record on fulfillment step history before creating new record.        **/
            for(Fulfillment_Step_History__c fh: oldestRecordList){
                    fh.Task_End_Date__c = system.now();
                    updatedRecordList.add(fh); 
                
            }
            System.debug('updatedRecordList in track Status method'+updatedRecordList);
            try{
            	update updatedRecordList;
            }catch(exception e){
                GeneralConstants.mailAnyExceptionToMe('trackStatus Method exception','trackStatus'+'update history end date failed',e);
            }            
        }
        for(Fullfilment_Item__c fItem :FI){
        	/* AD-30173 sshu : add insert a "procedural" record into the Task History with Workflow Status = "COMPLETE" before the record indicating "LIVE" is added.*/
        	if(fItem.Status__c == IfullfillTextConstant.FI_WORKFLOW_LIVE_STATUS && fItem.Transaction_Type__c == IfullfillTextConstant.FI_TRANSACTION_TYPE_CHANGE_REQUEST){
        		Fullfilment_Item__c temp = (Fullfilment_Item__c) fItem.clone(true, true); // true: preserve id ; true: deep clone
        		temp.Status__c = IfullfillTextConstant.FI_WORKFLOW_COMPLETE_STATUS;
        		Fulfillment_Step_History__c history = getNewTaskHistory(temp, MovesForwardFunction, MovesForwardTask, oldFIMap);
        		FSHlist.add(history);      
        	}
        	Fulfillment_Step_History__c history = getNewTaskHistory(fItem, MovesForwardFunction, MovesForwardTask, oldFIMap);
        	FSHlist.add(history);                                                 
        } // for loop ends      

       /**Insert the Fulfillment Step History     **/
       try{
          if(FSHlist.size()>0) 
            Insert FSHlist;
       }catch(exception trackStatusHistoryException){
            GeneralConstants.mailAnyExceptionToMe('trackStatus Method exception','trackStatus',trackStatusHistoryException);
       }                               
       system.debug('From Update trigger'+FSHlist);                      
    }
    
 	private static Fulfillment_Step_History__c getNewTaskHistory(Fullfilment_Item__c fItem, Boolean MovesForwardFunction, Boolean MovesForwardTask, map<id, fullfilment_item__c> oldFIMap){
 		 			/**Create Fulfillment Step History ***/
                     Fulfillment_Step_History__c FSH = new Fulfillment_Step_History__c();                             
                     FSH.Stage__c    = fItem.Current_Function_Name__c; 
                     FSH.Step__c     = fItem.Current_Task_Name__c;  
                     FSH.Target_Days_Function__c    = fItem.Current_Stage_Target_days__c;  
                     FSH.Target_Days_Task__c        = fItem.Current_Step_Target_days__c;                                                                  
                     FSH.Fullfilment_Item__c        = fItem.id;
                     FSH.Status__c                  = fItem.Status__c; 
                     FSH.Task_Start_Date__c         = System.now();                 
                     FSH.Closed_by__c               = fItem.lastmodifiedbyId;
                     FSH.Workflow_Id__c             = fItem.Workflow_Name__c;
                     FSH.Sequence__c                = fItem.Function_Sequence__c;
                     FSH.Task_Sequence__c           = fItem.Task_Sequence__c;
                     
                     string ownerId = string.valueof(fItem.OwnerId);
                     String oldOwnerId = string.valueof(oldFIMap.get(fItem.Id).Ownerid);
                     System.debug('oldFIMAP OWNER...'+oldFIMap.get(fItem.Id).Ownerid+'Reporting.'+oldFIMap.get(fItem.Id).Owner_Reporting__c);
                     System.debug('Current Owner '+fItem.Ownerid+'Reportiung'+fItem.Owner_Reporting__c);
 
                     if(ownerId.startswith(IfullfillTextConstant.OWNERVALUE)){ //in case of move back, WF coordinator, keep it with me and user to user owner change
                         FSH.Owner__c                   = fItem.Owner_Reporting__c;
                         FSH.ownerId                    = fItem.Ownerid;
                     }else if(ownerId.startswith(IfullfillTextConstant.QUEUEVALUE) && oldOwnerId.startswith(IfullfillTextConstant.QUEUEVALUE)){//this scenario is incase of records being sent from exception Queue to assign group or owner change from one queue to another queue
                         FSH.Owner__c                   = UserInfo.getName();
                         FSH.ownerId                    = UserInfo.getUserId();
                     }
                     else{ 
                     /** in case of normal move next where new owner is queue, history owner is the old owner of FI **/
                         FSH.Owner__c                   = oldFIMap.get(fItem.Id).Owner_Reporting__c;
                         FSH.ownerId                    = oldFIMap.get(fItem.Id).Ownerid;                     
                     }                     
                     FSH.Dashboard_Function__c      = fItem.Previous_Dashboard__c;
                     FSH.Rework_Function__c         = fItem.Previous_Function__c ;      
                     FSH.Rework_Function_Sequence__c= fItem.Previous_Function_Sequence__c; 
                     FSH.Rework_Task__c             = fItem.Previous_Task__c;
                     FSH.Rework_Task_Sequence__c    = fItem.Previous_Task_Sequence__c;                                          

                     /**Populate task end date for Complete, live, outed and cancelled status**/
             if(fItem.Status__c == IfullfillTextConstant.FI_WORKFLOW_COMPLETE_STATUS || fItem.Status__c == IfullfillTextConstant.FI_WORKFLOW_OUTED_STATUS || fItem.Status__c == IfullfillTextConstant.FI_WORKFLOW_CANCELED_STATUS || fItem.Status__c == IfullfillTextConstant.FI_WORKFLOW_LIVE_STATUS ){
                 FSH.Task_End_Date__c = system.now();
             }                                                                                                                                            
         /** Populate the 'Type' as per Rework/Reject on fulfillment Item **/
          system.debug('before updateing any item'+FSH.type__c);
          if(MovesForwardTask || MovesForwardFunction){FSH.type__c = IfullfillTextConstant.FI_NEW;}
          else if(fItem.In_Rework_Reject__c==IfullfillTextConstant.FI_REJECT){FSH.type__c = IfullfillTextConstant.FI_REJECT;}     
          else if(fItem.In_Rework_Reject__c==IfullfillTextConstant.FI_REWORK){FSH.type__c = IfullfillTextConstant.FI_REWORK;}                
          system.debug(FSH.type__c + MovesForwardFunction + MovesForwardTask);    
 		return FSH;
 	}      
 }